package org.light.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.light.core.Verb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.JavascriptBlock;
import org.light.domain.JavascriptMethod;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.domain.Type;
import org.light.easyui.EasyUIPositions;
import org.light.utils.FieldUtil;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class Export extends Verb implements EasyUIPositions {

	@Override
	public Method generateDaoImplMethod() throws Exception {
		return null;
	}	

	@Override
	public Method generateDaoMethodDefinition() throws Exception {
		return null;
	}

	@Override
	public Method generateServiceMethodDefinition() throws Exception {
		return null;
	}

	@Override
	public Method generateServiceImplMethod() throws Exception  {
		return null;
	}

	public Export(){
		super();
		this.setLabel("Excel导出");
	}
	
	public Export(Domain domain){
		super();
		this.domain = domain;
		this.setVerbName("Export"+this.domain.getCapFirstPlural());
		this.setLabel("Excel导出");
	}

	public Export(Domain domain, Set<Field> deniedFields){
		super();
		this.domain = domain;
		this.dbType = domain.getDbType();
		this.deniedFields = deniedFields;
		this.setVerbName("Export"+this.domain.getCapFirstPlural());
		this.setLabel("Excel导出");
	}

	@Override
	public Method generateControllerMethod() throws Exception {
		Method method = new Method();
		method.setStandardName("processRequest");
		method.setReturnType(new Type("void"));
		method.setThrowException(true);
		List<String> list = new ArrayList<String>();
		list.add("ServletException");
		list.add("IOException");
		method.setIsprotected(true);
		method.setOtherExceptions(list);
		method.addSignature(new Signature(1,"request",new Type("HttpServletRequest","javax.servlet.http")));
		method.addSignature(new Signature(2,"response",new Type("HttpServletResponse","javax.servlet.http")));
		method.addAdditionalImport("java.io.IOException");
		method.addAdditionalImport("javax.servlet.ServletException");
		method.addAdditionalImport("javax.servlet.http.HttpServlet");
		method.addAdditionalImport("javax.servlet.http.HttpServletRequest");
		method.addAdditionalImport("javax.servlet.http.HttpServletResponse");
		method.addAdditionalImport("java.util.List");
		method.addAdditionalImport("java.util.ArrayList");
		method.addAdditionalImport("java.io.OutputStream");
		method.addAdditionalImport("java.util.Arrays");
		method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getDomainSuffix()+"."+this.domain.getCapFirstDomainNameWithSuffix());
		method.addAdditionalImport(this.domain.getPackageToken()+".utils.POIExcelUtil");
		method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceSuffix()+"."+this.domain.getStandardName()+"Service");
		method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceimplSuffix()+"."+this.domain.getStandardName()+"ServiceImpl");
		method.addAdditionalImport(this.domain.getPackageToken()+".utils.StringUtil");

		for (Field f:this.domain.getFields()) {
			if (!this.deniedFields.contains(f)) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown)f;
					method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getDomainSuffix()+"."+dp.getTarget().getCapFirstDomainNameWithSuffix());
					method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceSuffix()+"."+dp.getTargetName()+"Service");
					method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceimplSuffix()+"."+dp.getTargetName()+"ServiceImpl");
				}
			}
		}

		if (this.domain.containsDateTime()) {
			method.addAdditionalImport(this.domain.getPackageToken()+".utils.DateUtil");
		}
		
		List<Writeable> sList = new ArrayList<Writeable>();
		sList.add(new Statement(1000L,2,"try(OutputStream out = response.getOutputStream()){"));
		sList.add(new Statement(2000L,3,"try{"));
		sList.add(new Statement(4000,4,this.domain.getStandardName()+"Service service  = new " + this.domain.getStandardName()+"ServiceImpl();"));
		long serial = 5000L;
		Set<String> dpDomainNames = new TreeSet<>();
		for (Field f:this.domain.getFields()) {
			if (!this.deniedFields.contains(f)) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown)f;
					dpDomainNames.add(dp.getTargetName());
				}
			}
		}
		for (String dName :dpDomainNames){
			sList.add(new Statement(serial,4,StringUtil.capFirst(dName)+"Service "+StringUtil.lowerFirst(dName)+"Service  = new " + StringUtil.capFirst(dName)+"ServiceImpl();"));
			serial += 1000L;
		}
		sList.add(new Statement(serial,4,"response.addHeader(\"Content-Disposition\", \"attachment;filename="+this.domain.getCapFirstPlural()+".xls\");"));
		sList.add(new Statement(serial+1000L,4,"List<"+this.domain.getCapFirstDomainNameWithSuffix()+"> list = service.listAll"+this.domain.getCapFirstPlural()+"();"));
		sList.add(new Statement(serial+4000L,4,"List<List<Object>> contents = new ArrayList<>();"));
		if  (domain.getLanguage().equalsIgnoreCase("english"))  {
			sList.add(new Statement(serial + 5000L,4,"String sheetName = \""+this.domain.getText()+" Information\";"));
		}else {
			sList.add(new Statement(serial + 5000L,4,"String sheetName = \""+this.domain.getText()+"信息表\";"));			
		}
		sList.add(new Statement(serial+6000L,4,"String [] headers = "+this.domain.generateFieldLabelsArrayStr(FieldUtil.filterDeniedFields(this.domain.getFields(),this.deniedFields))+";"));
		sList.add(new Statement(serial+6500L,4,"Boolean [] isImages = "+this.domain.generateIsImageFieldsArrayStr(FieldUtil.filterDeniedFields(this.domain.getFields(),this.deniedFields))+";"));
		sList.add(new Statement(serial+7000L,4,""));
		sList.add(new Statement(serial+8000L,4,"for ("+this.domain.getCapFirstDomainNameWithSuffix	()+" "+this.domain.getLowerFirstDomainName()+":list) {"));
		serial += 9000L;
		for (Field f:this.domain.getFields()) {
			if (!this.deniedFields.contains(f)) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown)f;
					sList.add(new Statement(serial,5,f.getFieldType()+ " "+f.getLowerFirstFieldName()+"0 = "+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"();"));
					sList.add(new Statement(serial+500L,5,dp.getTarget().getType()+" " +dp.getAliasName()+"Type0;"));
					sList.add(new Statement(serial+1000L,5,dp.getTarget().getDomainName().getFieldType()+" " +dp.getAliasName()+"Name0 = \"\";"));
					sList.add(new Statement(serial+2000L,5,"if ("+f.getLowerFirstFieldName()+"0 != null) {"));
					sList.add(new Statement(serial+2100L,6,dp.getAliasName()+"Type0 = "+StringUtil.lowerFirst(dp.getTargetName())+"Service.find"+dp.getTarget().getCapFirstDomainName()+"By"+dp.getTarget().getDomainId().getCapFirstFieldName()+"("+f.getLowerFirstFieldName()+"0);"));
					sList.add(new Statement(serial+2200L,6,"if ("+dp.getAliasName()+"Type0 !=null) "+dp.getAliasName()+"Name0 = "+dp.getAliasName()+"Type0.get"+dp.getTarget().getDomainName().getCapFirstFieldName()+"();"));
					sList.add(new Statement(serial+2300L,5,"}"));
					serial+=3000L;
				}
			}
		}
		String sc = "Object [] row = {";
		for (Field f:this.domain.getFields()) {
			if (!this.deniedFields.contains(f)) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown)f;
					sc += dp.getAliasName() + "Name0,";
				}else {
					if (f.getFieldType().equalsIgnoreCase("String")||f.getFieldType().equalsIgnoreCase("image")) {
						sc += this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"(),";
					} else if (f.getFieldType().equalsIgnoreCase("date")) {
						sc += "DateUtil.utilDateToString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()),";
					} else if (f.getFieldType().equalsIgnoreCase("datetime")) {
						sc += "DateUtil.utilDateTimeToString(" + this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()),";
					} else {
						sc += "StringUtil.toNullString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()),";
					}
				}
			}
		}
		if (this.domain.getFields()!=null && this.domain.getFields().size()>0) {
			sc = sc.substring(0,sc.length()-1);
		}
		sc += "};";
		sList.add(new Statement(serial,5,sc));
		sList.add(new Statement(serial+1000L,5,"contents.add(Arrays.asList(row));"));
		sList.add(new Statement(serial+2000L,4,"}"));
		sList.add(new Statement(serial+3000L,4,""));
		sList.add(new Statement(serial+4000L,4,"POIExcelUtil.exportExcelWorkbookWithImage(out, sheetName, Arrays.asList(headers), contents, Arrays.asList(isImages));"));
		sList.add(new Statement(serial+5000L,3,"} catch (Exception e) {"));
		sList.add(new Statement(serial+6000L,4,"ServletException se = new ServletException();"));
		sList.add(new Statement(serial+7000L,4,"se.setStackTrace(e.getStackTrace());"));
		sList.add(new Statement(serial+8000L,4,"throw se;"));
		sList.add(new Statement(serial+9000L,3,"}"));	
		sList.add(new Statement(serial+10000L,2,"}"));	
		method.setMethodStatementList(WriteableUtil.merge(sList));		
		return method;
	}

	@Override
	public JavascriptBlock generateEasyUIJSButtonBlock() throws Exception {
		JavascriptBlock block = new JavascriptBlock();
		block.setSerial(100);
		block.setStandardName("export"+domain.getCapFirstPlural());
		StatementList sl = new StatementList();
		sl.add(new Statement(1000,0, "{"));
		sl.add(new Statement(2000,1, "text:'Excel导出',"));
		sl.add(new Statement(3000,1, "iconCls:'icon-sum',"));
		sl.add(new Statement(4000,1, "handler:function(){"));
		sl.add(new Statement(5000,2, "window.location.href=\"../"+this.domain.getControllerPackagePrefix()+this.domain.getLowerFirstDomainName()+domain.getControllerNamingSuffix()+"/export"+this.domain.getCapFirstPlural()+"\";"));
		sl.add(new Statement(6000,1, "}"));
		sl.add(new Statement(7000,0, "}"));
		block.setMethodStatementList(sl);
		return block;			
	}

	@Override
	public JavascriptMethod generateEasyUIJSActionMethod() throws Exception {
		return null;	
	}
	
	@Override
	public Method generateDummyDaoImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDummyServiceImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDummyDaoMethodDefinition() throws Exception {
		return null;
	}
}
